﻿#include <libini/item.h>
#include <libini/string.h>


// constructor
Xanadu::ini::item::item() noexcept
{
	this->_memberComment.clear();
	this->_memberKey = "";
	this->_memberValue = "";
}

// constructor
Xanadu::ini::item::item(const std::string& _String) noexcept
{
	this->_memberComment.clear();
	this->_memberKey = "";
	this->_memberValue = "";
	this->setData(_String);
}

// constructor
Xanadu::ini::item::item(const Xanadu::ini::item& _Other) noexcept
{
	this->_memberComment = _Other._memberComment;
	this->_memberKey = _Other._memberKey;
	this->_memberValue = _Other._memberValue;
}

// destructor
Xanadu::ini::item::~item() noexcept
{
}



// operator overload =
Xanadu::ini::item& Xanadu::ini::item::operator = (const Xanadu::ini::item& _Other) noexcept
{
	this->_memberComment = _Other._memberComment;
	this->_memberKey = _Other._memberKey;
	this->_memberValue = _Other._memberValue;
	return *this;
}



// Set the data for the row
void Xanadu::ini::item::setData(const std::string& _String) noexcept
{
	if(!_String.empty())
	{
		auto 		vCommentString = std::string();
		auto		vIndex = 0;
		auto		vFind = _String.find(LIBINI_NEWLINE_STRING, vIndex);
		while (vFind != std::string::npos)
		{
			auto		vLineString = _String.substr(vIndex, vFind - vIndex);
			if(!vLineString.empty())
			{
				if(vLineString[0] == LIBINI_EXPLAIN_CHAR)
				{
					vCommentString += vLineString;
				}
				else
				{
					auto		vFindKey = vLineString.find('=');
					if(vFindKey != std::string::npos)
					{
						this->setKey(vLineString.substr(0, vFindKey));
						this->setValue(vLineString.substr(vFindKey + 1));
					}
					break;
				}
			}

			vIndex = vFind;
			vFind = _String.find(LIBINI_NEWLINE_STRING, vIndex);
		};
		this->setComment(vCommentString);
	}
}



// Is it empty
bool Xanadu::ini::item::empty() const noexcept
{
	return this->_memberKey.empty();
}

// Does it exist
bool Xanadu::ini::item::exist() const noexcept
{
	return !this->empty();
}

// Get comment
std::string Xanadu::ini::item::comment() const noexcept
{
	return Xanadu::ini::explain::toString(this->_memberComment);
}

// Get key
std::string Xanadu::ini::item::key() const noexcept
{
	return this->_memberKey;
}

// Get value
std::string Xanadu::ini::item::value() const noexcept
{
	return this->_memberValue;
}



// Set comment
void Xanadu::ini::item::setComment(const std::string& _Comment) noexcept
{
	this->_memberComment = Xanadu::ini::explain::fromString(_Comment);
}

// Set comment
void Xanadu::ini::item::setComment(const std::list<std::string>& _Comments) noexcept
{
	this->_memberComment = Xanadu::ini::explain::fromString(_Comments);
}

// Set key
void Xanadu::ini::item::setKey(const std::string& _Key) noexcept
{
	this->_memberKey = _Key;
	while(!this->_memberKey.empty() && std::isspace(this->_memberKey[this->_memberKey.size() - 1]) != 0)
	{
		this->_memberKey.pop_back();
	}
}

// Set value
void Xanadu::ini::item::setValue(const std::string& _Value) noexcept
{
	this->_memberValue = _Value;
	while(!this->_memberValue.empty() && std::isspace(this->_memberValue[0]) != 0)
	{
		this->_memberValue.erase(this->_memberValue.begin());
	}
}



// Convert to string
std::string Xanadu::ini::item::toString() const noexcept
{
	if(this->key().empty())
	{
		return "";
	}
	else
	{
		return this->comment() + this->key() + "=" + this->value();
	}
}

// Format from one or more lines of strings
Xanadu::ini::item Xanadu::ini::item::fromStrings(const std::list<std::string>& _Strings) noexcept
{
	auto 		vItem = Xanadu::ini::item();
	auto 		vIterator = _Strings.begin();

	// Get comment and section
	auto 		vCommentStrings = std::list<std::string>();
	for(; vIterator != _Strings.end(); ++vIterator)
	{
		if(Xanadu::ini::string::is_empty(*vIterator) || Xanadu::ini::string::is_explain(*vIterator))
		{
			vCommentStrings.push_back(*vIterator);
		}
		if(Xanadu::ini::string::is_key(*vIterator))
		{
			auto 		vFind = vIterator->find(LIBINI_KEY_DIVISION);
			if(vFind != std::string::npos)
			{
				vItem.setKey(vIterator->substr(0, vFind));
				vItem.setValue(vIterator->substr(vFind + 1));
			}
			++vIterator;
			break;
		}
	}
	vItem._memberComment = Xanadu::ini::explain::fromString(vCommentStrings);
	return vItem;
}
